package com.zhao.dota.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhao.dota.config.WechatConfig;
import com.zhao.dota.contant.CacheConstant;
import com.zhao.dota.exception.WechatException;
import com.zhao.dota.struct.Unlimited;
import com.zhao.dota.struct.WechatSession;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.UUID;

@Service
@Slf4j
@CacheConfig(cacheNames = CacheConstant.WECHAT)
public class WechatService {

    private static final String WX_UNLIMITED_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN";

    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

    private static final String ACCESS_TOKEN_KEY_PREFIX = "'wechat:access_token'";

    private static final String CODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
    @Resource
    private WechatConfig wechatConfig;
    @Resource
    private OkHttpClient okHttpClient;
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private WechatService wechatService;

    public WechatSession code2Session(String code) {
        String url = String.format(CODE_2_SESSION_URL, wechatConfig.getAppId(), wechatConfig.getAppSecret(), code);
        Request request = new Request.Builder()
                .get()
                .url(url)
                .build();
        WechatSession wechatSession;
        try {
            Response response = okHttpClient.newCall(request).execute();
            String string = response.body().string();
            wechatSession = objectMapper.readValue(string, WechatSession.class);
            return wechatSession;
        } catch (IOException | NullPointerException e) {
            log.error("获取微信session失败：" + e.getLocalizedMessage(), e);
            return null;
        }
    }

    public byte[] loginWxacode(String uuid) {
        String accessToken = wechatService.getAccessToken();
        String url = WX_UNLIMITED_URL.replace("ACCESS_TOKEN", accessToken);

        Unlimited unlimited = new Unlimited("pages/LoginPc/index", uuid);
        unlimited.setAutoColor(true);
        unlimited.setWidth(200);

        try {
            RequestBody requestBody = RequestBody.create(MediaType.get("application/json"), objectMapper.writeValueAsString(unlimited));
            Request request = new Request.Builder()
                    .post(requestBody)
                    .url(url)
                    .build();
            Response response = okHttpClient.newCall(request).execute();
            return response.body().bytes();
        } catch (IOException | NullPointerException e) {
            return null;
        }
    }

//    @PostConstruct
    public void init() {
        refreshAccessToken();
    }

    @Scheduled(cron = "0 0 0/1 * * ?")
    public void refreshAccessToken() {
        wechatService.deleteAccessToken();
        wechatService.getAccessToken();
    }

    @CacheEvict(key = ACCESS_TOKEN_KEY_PREFIX)
    public void deleteAccessToken() {

    }

    @Cacheable(key = ACCESS_TOKEN_KEY_PREFIX, unless = "#result == null")
    public String getAccessToken() {
        String url = ACCESS_TOKEN_URL.replace("APPID", wechatConfig.getAppId()).replace("APPSECRET", wechatConfig.getAppSecret());
        Request request = new Request.Builder()
                .get()
                .url(url)
                .build();
        String result;
        try {
            if (log.isInfoEnabled()) {
                log.info("获取access token: {}", url);
            }
            Response response = okHttpClient.newCall(request).execute();
            result = response.body().string();
        } catch (IOException | NullPointerException e) {
            log.error("获取微信access_token失败, code:{}, desc: {}" + e.getLocalizedMessage(), e);
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(result);
        int status = jsonObject.getIntValue("errcode");
        if (status == -1) {
            throw new WechatException("获取微信access_token失败");
        }
        if (status == 0) {
            return jsonObject.getString("access_token");
        }
        log.error("获取微信access_token失败, code:{}, desc: {}", status, jsonObject.getString("errmsg"));
        return null;
    }

}
